package com.qs.cwams.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.qs.common.framework.dto.PageResult;
import com.qs.common.framework.dto.QsPage;
import com.qs.common.framework.dto.QsResult;
import com.qs.common.framework.util.ConvertUtil;
import com.qs.cwams.mapper.AtteConfigMapper;
import com.qs.cwams.mapper.AtteRecordMapper;
import com.qs.cwams.mapper.AtteRuleMapper;
import com.qs.cwams.pojo.domain.AtteConfigDO;
import com.qs.cwams.pojo.domain.AtteRecordDO;
import com.qs.cwams.pojo.domain.AtteRuleDO;
import com.qs.cwams.pojo.view.AtteDateVO;
import com.qs.cwams.pojo.view.AtteRecordVO;
import com.qs.cwams.pojo.view.AtteRuleVO;
import com.qs.cwams.pojo.view.AtteStatisticVO;
import com.qs.cwams.service.AtteRecordService;
import com.qs.cwams.service.AtteRuleService;
import com.qs.cwams.util.AtteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author suncheng
 */
@Service
public class AtteRuleServiceImpl implements AtteRuleService {

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private AtteRecordMapper atteRecordMapper;
    @Autowired
    private AtteConfigMapper atteConfigMapper;
    @Autowired
    private AtteRuleMapper atteRuleMapper;

    private LocalDateTime getLocalTime(String str, int year, int month, int day, String ss) {
        String time = String.format("%s-%s-%s %s:%s", year, String.format("%02d", month), String.format("%02d", day), str, ss);
        return LocalDateTime.parse(time, formatter);
    }

    @Override
    public QsResult setRule(List<AtteRuleVO> rules) {
        List<AtteRuleDO> insertList = new ArrayList<>();
        List<AtteRuleDO> updateList = new ArrayList<>();
        rules.forEach(rule -> {
            if (rule.getId() == null) {
                insertList.add(ConvertUtil.copy(rule, AtteRuleDO.class));
            } else {
                updateList.add(ConvertUtil.copy(rule, AtteRuleDO.class));
            }
        });
        int res = 0;
        if (insertList.size() > 0) {
            res += insertList.stream().map(item -> atteRuleMapper.insert(item)).reduce(0, Integer::sum);
        }
        if (updateList.size() > 0) {
            res += updateList.stream().map(item -> atteRuleMapper.updateById(item)).reduce(0, Integer::sum);
        }
        return res == rules.size() ? QsResult.ok() : QsResult.fail(500, "设置失败");
    }

    @Override
    public QsResult delRule(List<Long> ruleIds) {
        atteRuleMapper.deleteBatchIds(ruleIds);
        return QsResult.ok();
    }

    @Override
    public QsResult queryRule(AtteRuleVO rule, QsPage page) {
        Page<AtteRuleDO> rulePage = Page.of(page.getCurPage(), page.getPageSize());
        atteRuleMapper.selectPage(rulePage, new LambdaQueryWrapper<AtteRuleDO>()
                .eq(rule.getAtteYear() != null, AtteRuleDO::getAtteYear, rule.getAtteYear())
                .eq(rule.getAtteMonth() != null, AtteRuleDO::getAtteMonth, rule.getAtteMonth())
                .eq(rule.getAtteDay() != null, AtteRuleDO::getAtteDay, rule.getAtteDay())
                .eq(rule.getType() != null, AtteRuleDO::getType, rule.getType())
                .orderByAsc(AtteRuleDO::getAtteYear, AtteRuleDO::getAtteMonth, AtteRuleDO::getAtteDay));
        page.setTotal(rulePage.getTotal());
        PageResult<AtteRuleVO> pageResult = new PageResult<>(ConvertUtil.listCopy(rulePage.getRecords(), AtteRuleVO.class), page);
        return QsResult.ok().setResult(pageResult);
    }

    @Override
    public QsResult setAdd() {
        LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
        int year = now.getYear();
        int month = now.getMonth().getValue();

        long count = atteRuleMapper.selectCount(new LambdaQueryWrapper<AtteRuleDO>()
                .eq(AtteRuleDO::getAtteYear, year)
                .eq(AtteRuleDO::getAtteMonth, month));
        if (count == 0) {
            // 生成当月额外加班日期和时间
            AtteConfigDO addOfWeekConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                    .eq(AtteConfigDO::getConfigCode, "AddOfWeek"));
            AtteConfigDO addOfTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                    .eq(AtteConfigDO::getConfigCode, "AddOfTime"));

            String startTime;
            String endTime;
            if (0 == Integer.parseInt(addOfTimeConfig.getConfigValue())) {
                AtteConfigDO amTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                        .eq(AtteConfigDO::getConfigCode, "AmTime"));
                AtteConfigDO pmTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                        .eq(AtteConfigDO::getConfigCode, "PmTime"));
                startTime = amTimeConfig.getConfigValue().split("-")[0];
                endTime = pmTimeConfig.getConfigValue().split("-")[1];
            } else if (1 == Integer.parseInt(addOfTimeConfig.getConfigValue())) {
                AtteConfigDO amTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                        .eq(AtteConfigDO::getConfigCode, "AmTime"));
                startTime = amTimeConfig.getConfigValue().split("-")[0];
                endTime = amTimeConfig.getConfigValue().split("-")[1];
            } else if (2 == Integer.parseInt(addOfTimeConfig.getConfigValue())) {
                AtteConfigDO pmTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                        .eq(AtteConfigDO::getConfigCode, "PmTime"));
                startTime = pmTimeConfig.getConfigValue().split("-")[0];
                endTime = pmTimeConfig.getConfigValue().split("-")[1];
            } else {
                return QsResult.fail(500, "未知考勤类型");
            }
            // 当月第一个加班日和最后一天
            DayOfWeek dayOfWeek = DayOfWeek.of(Integer.parseInt(addOfWeekConfig.getConfigValue()));
            LocalDateTime firstAddDay = now.with(TemporalAdjusters.firstInMonth(dayOfWeek));
            LocalDateTime lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
            // 当月所有加班日
            AtteRuleDO atteRuleDO;
            int day = firstAddDay.getDayOfMonth();
            while (day <= lastDay.getDayOfMonth()) {
                atteRuleDO = new AtteRuleDO();
                atteRuleDO.setAtteYear(year);
                atteRuleDO.setAtteMonth(month);
                atteRuleDO.setAtteDay(day);
                atteRuleDO.setStartTime(Date.from(getLocalTime(startTime, year, month, day, "00").atZone(ZoneId.systemDefault()).toInstant()));
                atteRuleDO.setEndTime(Date.from(getLocalTime(endTime, year, month, day, "00").atZone(ZoneId.systemDefault()).toInstant()));
                atteRuleMapper.insert(atteRuleDO);
                day += 7;
            }
        }
        return QsResult.ok();
    }
}
